/**
 * Copyright (c) 2017-2018,Retire 吴益峰 (372310383@qq.com).
 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package io.jplus.utils;

import com.jfinal.template.Engine;
import io.jboot.exception.JbootException;

import javax.inject.Named;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;

/**
 * @author Retire 吴益峰 （372310383@qq.com）
 * @version V1.0
 * @Package io.jplus.utils
 */
public class StringUtils {

    static final Engine ENGINE = new Engine("JplusCacheRender");
    private static final Random RANDOM = new Random();

    // 随机字符串
    private static final String _INT = "0123456789";
    private static final String _STR = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
    private static final String _ALL = _INT + _STR;

    /**
     * 生成的随机数类型
     *
     * @author L.cm
     * @email: 596392912@qq.com
     * @site: http://www.dreamlu.net
     * @date 2015年4月20日下午9:15:23
     */
    public static enum RandomType {
        INT, STRING, ALL;
    }

    /**
     * 随机数生成
     *
     * @param count
     * @return
     */
    public static String random(int count, RandomType randomType) {
        if (count == 0) return "";
        if (count < 0) {
            throw new IllegalArgumentException("Requested random string length " + count + " is less than 0.");
        }
        char[] buffer = new char[count];
        for (int i = 0; i < count; i++) {
            if (randomType.equals(RandomType.INT)) {
                buffer[i] = _INT.charAt(RANDOM.nextInt(_INT.length()));
            } else if (randomType.equals(RandomType.STRING)) {
                buffer[i] = _STR.charAt(RANDOM.nextInt(_STR.length()));
            } else {
                buffer[i] = _ALL.charAt(RANDOM.nextInt(_ALL.length()));
            }
        }
        return new String(buffer);
    }

    public static String converteToString(Object object) {
        if (object == null) {
            return "null";
        }
        if (!isPrimitive(object.getClass())) {
            return null;
        }

        if (object instanceof java.util.Date) {
            return String.valueOf(((java.util.Date) object).getTime());
        }

        if (object instanceof java.sql.Date) {
            return String.valueOf(((java.sql.Date) object).getTime());
        }
        if (object instanceof java.sql.Timestamp) {
            return String.valueOf(((java.sql.Timestamp) object).getTime());
        }
        if (object instanceof java.sql.Time) {
            return String.valueOf(((java.sql.Time) object).getTime());
        }

        return String.valueOf(object);
    }

    public static String engineRender(String template, Method method, Object[] arguments) {

        Map<String, Object> datas = new HashMap();
        int x = 0;
        /**
         * 在java8下，通过添加 -parameters 进行编译，可以获取 Parameter 的编译前的名字
         * 否则 只能获取 编译后的名字
         */
        for (Parameter p : method.getParameters()) {
            if (!p.isNamePresent()) {
                break;
            }
            datas.put(p.getName(), arguments[x++]);
        }


        /**
         * 保证在java8没有添加 -parameters 的时候，可以通过注解的方式获取参数，保证兼容。
         * 同时，可以通过注解的方式覆盖 默认名称。
         */
        Annotation[][] annotationss = method.getParameterAnnotations();
        for (int i = 0; i < annotationss.length; i++) {
            for (int j = 0; j < annotationss[i].length; j++) {
                Annotation annotation = annotationss[i][j];
                if (annotation.annotationType() == Named.class) {
                    Named named = (Named) annotation;
                    datas.put(named.value(), arguments[i]);
                } else if (annotation.annotationType() == com.google.inject.name.Named.class) {
                    com.google.inject.name.Named named = (com.google.inject.name.Named) annotation;
                    datas.put(named.value(), arguments[i]);
                }
            }
        }

        try {
            return ENGINE.getTemplateByString(template).renderToString(datas);
        } catch (Throwable throwable) {
            throw new JbootException("render template is error! template is " + template, throwable);
        }

    }

    static boolean isPrimitive(Class clazz) {
        return clazz == String.class
                || clazz == Integer.class
                || clazz == int.class
                || clazz == Long.class
                || clazz == long.class
                || clazz == Double.class
                || clazz == double.class
                || clazz == Float.class
                || clazz == float.class
                || clazz == Boolean.class
                || clazz == boolean.class
                || clazz == BigDecimal.class
                || clazz == BigInteger.class
                || clazz == java.util.Date.class
                || clazz == java.sql.Date.class
                || clazz == java.sql.Timestamp.class
                || clazz == java.sql.Time.class;


    }
}
